﻿#include "FITKNastranBDFIOTool.h"
#include "FITKNastranBDFReader.h"
#include "FITKNastranBDFWriter.h"

#include "FITK_Interface/FITKInterfaceModel/FITKComponentManager.h"
#include "FITK_Interface/FITKInterfacePhysics/FITKSectionAssign.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAbstractSection.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaSectionAssignBeam.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaSectionAssignSolidHomogenous.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaSectionAssignShellHomogeneous.h"

#include "FITK_Component/FITKAbaqusData/FITKAbaqusPart.h"
#include "FITK_Component/FITKAbaqusData/FITKDataCase.h"

#include <QRegularExpression>

namespace Nastran
{
    FITKNastranBDFIOReaderTool::FITKNastranBDFIOReaderTool(FITKNastranBDFReader* readerBDF) :
        _reader(readerBDF)
    {

    }

    void FITKNastranBDFIOReaderTool::setCaseData(AbaqusData::FITKDataCase *caseData)
    {
        _caseData = caseData;
    }

    void FITKNastranBDFIOReaderTool::setPartData(AbaqusData::FITKAbaqusPart * partData)
    {
        _partData = partData;
    }

    QStringList FITKNastranBDFIOReaderTool::readNastranBDFLineSpliter()
    {
        //获取数据
        QString currentLine = _reader->getCurrentLine();
        QStringList splitStr;
        //判断条件
        int formatType = 0;
        QRegularExpression condition("[a-zA-Z]");
        //长格式
        if (currentLine.contains("*"))
        {
            while (!_reader->atEnd())
            {
                //读取一行数据
                QString line = _reader->readLine();
                if (line.isEmpty()) continue;
                if (formatType != 0 && condition.match(line.at(0)).hasMatch())
                    break;
                if (formatType == 0)
                    splitStr.append(line.mid(0, 8));
                //截取数据
                for (int i = 8; i < line.length(); i += 16) {
                    QString data = line.mid(i, 16);
                    splitStr.append(data);
                    if (i == 56)
                        break;
                }
                formatType = 2;
            }
        }
        //短格式
        else
        {
            while (!_reader->atEnd())
            {
                //读取一行数据
                QString line = _reader->readLine();
                if (line.isEmpty()) continue;
                if (formatType != 0 && condition.match(line.at(0)).hasMatch())
                    break;
                int beginSplitIndex = 0;
                if (formatType != 0)
                    beginSplitIndex = 8;
                //截取数据
                for (int i = beginSplitIndex; i < line.length(); i += 8) {
                    QString data = line.mid(i, 8);
                    splitStr.append(data);
                    if (i == 64)
                        break;
                }
                formatType = 1;
            }
        }
        return splitStr;
    }

    double FITKNastranBDFIOReaderTool::stringToDouble(QString value, bool &ok)
    {
        ok = false;
        //转小写
        value = value.trimmed().toLower();
        //数据转化
        for (int j = 0; j < value.size(); ++j)
        {
            QChar ch = value.at(j);
            if (ch == '.')
            {
                if (j == 0 || (j == 1 && value.at(0) == '-'))
                {
                    value.insert(j, '0');
                    ++j;
                }
            }
            else if (j > 0 && ch == '-')
            {
                if (j + 1 < value.size() && value.at(j - 1) == 'e') continue;
                value.insert(j, 'e');
                ++j;
            }
        }
        return value.toDouble(&ok);
    }

    void FITKNastranBDFIOReaderTool::insertElementProp(int pID, int elementID)
    {
        if (!_pIDElementID.contains(pID))
            _pIDElementID.insert(pID, QList<int>());
        _pIDElementID[pID].append(elementID);
    }

    void FITKNastranBDFIOReaderTool::insertPIDMID(int pID, QList<int> mID)
    {
        _pIDMID.insert(pID, mID);
    }

    void FITKNastranBDFIOReaderTool::insertDataMapping(ReadMappingType type, int readID, int objId)
    {
        if (!_idIDMapping.contains(type))
            _idIDMapping.insert(type, QHash<int, int>());
        _idIDMapping[type].insert(readID, objId);
    }

    void FITKNastranBDFIOReaderTool::updateData()
    {
        if (!_caseData || !_partData) return;
        //获取set集合管理器、截面指派和截面属性管理器
        Interface::FITKComponentManager* componentManager = _partData->getComponentManager();
        Interface::FITKSectionAssignManager* sectionAssignManager = _partData->getSectionAssignManager();
        Interface::FITKAbstractSectionManager* sectionManager = _caseData->getSectionManager();
        if (!componentManager || !sectionAssignManager || !sectionManager) return;
        //获取映射表
        QHash<int, int> pIDSection = _idIDMapping[ReadMappingType::ReadPIDSection];
        QHash<int, int> mIDMat = _idIDMapping[ReadMappingType::ReadMIDMaterial];
        //开始更新并创建指派
        for (QHash<int, QList<int>>::iterator iter = _pIDElementID.begin(); iter != _pIDElementID.end(); ++iter)
        {
            int pID = iter.key();
            // Create a new model set for the current PID
            Interface::FITKModelSet* pidSet = new Interface::FITKModelSet();
            pidSet->setDataObjectName(componentManager->checkName("Set-1"));
            pidSet->setModelSetType(Interface::FITKModelEnum::FMSElem);
            pidSet->setParentDataID(_partData->getDataObjectID());
            // Add nodes to the model set
            for (int node : iter.value())
                pidSet->appendMember(node);
            // Add the model set to the component manager
            componentManager->appendDataObj(pidSet);
            //获取截面
            if (!pIDSection.contains(pID))continue;
            int sectionID = pIDSection.value(pID);
            Interface::FITKAbaAbastractSection* pSection = dynamic_cast<Interface::FITKAbaAbastractSection*>(sectionManager->getDataByID(sectionID));
            if (!pSection) continue;
            //设置截面材料
            QList<int> mIDList = _pIDMID[pID];
            for (int i = 0; i < mIDList.size(); ++i)
                pSection->setMaterial(mIDMat[mIDList.at(i)], i);
            Interface::FITKAbaAbastractSection::FITKAbaSectionType type = pSection->getSectionType();
            // Create and assign section
            Interface::FITKSectionAssign* assign = nullptr;
            if (type == Interface::FITKAbaAbastractSection::FITKAbaSectionType::Beam)
                assign = new Interface::FITKAbaSectionAssignBeam;
            else if (type == Interface::FITKAbaAbastractSection::FITKAbaSectionType::ShellHomogeneous)
                assign = new Interface::FITKAbaSectionAssignShellHomogeneous;
            else if (type == Interface::FITKAbaAbastractSection::FITKAbaSectionType::SolidHomogeneous)
                assign = new Interface::FITKAbaSectionAssignSolidHomogenous;
            if (assign == nullptr) continue;
            assign->assign(pidSet->getDataObjectID(), pSection->getDataObjectID());
            sectionAssignManager->appendDataObj(assign);
        }
    }

    FITKNastranBDFIOWriterTool::FITKNastranBDFIOWriterTool(FITKNastranBDFWriter* writerBDF) :
        _writer(writerBDF)
    {

    }

    void FITKNastranBDFIOWriterTool::setCaseData(AbaqusData::FITKDataCase *caseData)
    {
        _caseData = caseData;
    }

    void FITKNastranBDFIOWriterTool::setPartData(AbaqusData::FITKAbaqusPart * partData)
    {
        _partData = partData;
    }

    int FITKNastranBDFIOWriterTool::getPropIDByEID(int eID)
    {
        if (_eIDPropIDMapping.contains(eID))
            return _eIDPropIDMapping[eID];
        return 0;
    }

    bool FITKNastranBDFIOWriterTool::writeData(QStringList& data)
    {
        if (!_writer || data.isEmpty()) return false;
        QTextStream* stream = _writer->getStream();
        if (!stream) return false;
        int count = data.size();
        //写出关键字
        QString keywork = data.at(0);
        if (_formatType == 2)
            keywork = QString("%1*").arg(keywork);
        for (int i = keywork.size(); i < 8; ++i)
            keywork.append(' ');
        *stream << keywork;
        //短格式
        if (_formatType == 1)
        {
            for (int i = 1; i < count; ++i)
            {
                *stream << QString("%1").arg(data.at(i), 8, ' ');
                if (i % 8 == 0 && i < count - 1)
                {
                    //切换行
                    *stream << "        " << endl;
                    *stream << "        ";
                }
            }
        }
        //长格式
        else if (_formatType == 2)
        {
            for (int i = 1; i < count; ++i)
            {
                *stream << QString("%1").arg(data.at(i), 16, ' ');
                if (i % 4 == 0 && i < count - 1)
                {
                    //切换行
                    *stream << "        " << endl;
                    *stream << "*       ";
                }
            }
        }
        *stream << endl;
        return true;
    }

    QString FITKNastranBDFIOWriterTool::doubleToString(double value, bool &ok)
    {
        ok = false;
        QString result;
        //短格式
        if (_formatType == 1)
        {

        }
        //长格式
        else if (_formatType == 2)
            result = QString::number(value, 'E', 6);
        ok = true;
        return result;
    }

    void FITKNastranBDFIOWriterTool::updateData()
    {
        if (!_caseData || !_partData) return;
        //获取set集合管理器、截面指派和截面属性管理器
        Interface::FITKComponentManager* componentManager = _partData->getComponentManager();
        Interface::FITKSectionAssignManager* sectionAssignManager = _partData->getSectionAssignManager();
        Interface::FITKAbstractSectionManager* sectionManager = _caseData->getSectionManager();
        if (!componentManager || !sectionAssignManager || !sectionManager) return;
        //通过截面指派获取数据
        int count = sectionAssignManager->getDataCount();
        for (int i = 0; i < count; ++i)
        {
            Interface::FITKSectionAssign* assign = sectionAssignManager->getDataByIndex(i);
            if (!assign) continue;
            int setID = assign->getModelID();
            int sectionID = assign->getSectionID();
            Interface::FITKModelSet* set = dynamic_cast<Interface::FITKModelSet*>(componentManager->getDataByID(setID));
            Interface::FITKAbstractSection* section = sectionManager->getDataByID(sectionID);
            if (!set || !section || set->getModelSetType() != Interface::FITKModelEnum::FITKModelSetType::FMSElem) continue;
            QList<int> idList = set->getAbsoluteMember();
            //设置映射表
            for (QList<int>::iterator iter = idList.begin(); iter != idList.end(); ++iter)
                _eIDPropIDMapping.insert(*iter, sectionID);
        }
    }

}
